Project Raijin Logo

Unstructured Grid Visualization Cookbook


Overview

If you have an introductory paragraph, lead with it here! Keep it short and tied to your material, then be sure to continue into the required list of topics below,

  1. This is a numbered list of the specific topics

  2. These should map approximately to your main sections of content

  3. Or each second-level, ##, header in your notebook

  4. Keep the size and scope of your notebook in check

  5. And be sure to let the reader know up front the important concepts they’ll be leaving with

Prerequisites

This section was inspired by this template of the wonderful The Turing Way Jupyter Book.

Following your overview, tell your reader what concepts, packages, or other background information they’ll need before learning your material. Tie this explicitly with links to other pages here in Foundations or to relevant external resources. Remove this body text, then populate the Markdown table, denoted in this cell with | vertical brackets, below, and fill out the information following. In this table, lay out prerequisite concepts by explicitly linking to other Foundations material or external resources, or describe generally helpful concepts.

Label the importance of each concept explicitly as helpful/necessary.

Concepts

Importance

Notes

Intro to Cartopy

Necessary

Understanding of NetCDF

Helpful

Familiarity with metadata structure

Project management

Helpful

  • Time to learn: estimate in minutes. For a rough idea, use 5 mins per subsection, 10 if longer; add these up for a total. Safer to round up and overestimate.

  • System requirements:

    • Populate with any system, version, or non-Python software requirements if necessary

    • Otherwise use the concepts table above and the Imports section below to describe required packages as necessary

    • If no extra requirements, remove the System requirements point altogether


Imports

Begin your body of content with another --- divider before continuing into this section, then remove this body text and populate the following code cell with all necessary Python imports up-front:

# Organization and data handling
import numpy as np
import pandas as pd
import uxarray as ux
import xarray as xr
import time
import requests

# General Plotting
import cartopy.crs as ccrs
import cartopy.feature as cfeature

# Plotting with matplotlib
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

# Plotting with datashader
import holoviews as hv
import hvplot.pandas
import geoviews.feature as gf

Dataset

# Load data files from web
ds_file_480 = requests.get("https://web.lcrc.anl.gov/public/e3sm/inputdata/share/meshes/mpas/ocean/oQU480.230422.nc").content
ds_file_120 = requests.get("https://web.lcrc.anl.gov/public/e3sm/inputdata/share/meshes/mpas/ocean/oQU120.230424.nc").content

# Open datasets from files
ds_480 = xr.open_dataset(ds_file_480)
ds_120 = xr.open_dataset(ds_file_120)
ds_480
<xarray.Dataset>
Dimensions:                   (nEdges: 5754, maxEdges2: 12, TWO: 2,
                               nVertices: 3947, vertexDegree: 3, nCells: 1791,
                               nVertLevels: 60, maxEdges: 6, Time: 1)
Dimensions without coordinates: nEdges, maxEdges2, TWO, nVertices,
                                vertexDegree, nCells, nVertLevels, maxEdges,
                                Time
Data variables: (12/49)
    edgesOnEdge               (nEdges, maxEdges2) int32 ...
    weightsOnEdge             (nEdges, maxEdges2) float64 ...
    cellsOnEdge               (nEdges, TWO) int32 ...
    verticesOnEdge            (nEdges, TWO) int32 ...
    angleEdge                 (nEdges) float64 ...
    dcEdge                    (nEdges) float64 ...
    ...                        ...
    refTopDepth               (nVertLevels) float64 ...
    refZMid                   (nVertLevels) float64 ...
    refLayerThickness         (nVertLevels) float64 ...
    layerThickness            (Time, nCells, nVertLevels) float64 ...
    ssh                       (Time, nCells) float64 ...
    zMid                      (Time, nCells, nVertLevels) float64 ...
Attributes: (12/14)
    model_name:     mpas
    core_name:      ocean
    source:         MPAS
    Conventions:    MPAS
    git_version:    v4.0-630-gaa1be43
    on_a_sphere:    YES
    ...             ...
    x_period:       0.0
    y_period:       0.0
    history:        Sat Apr 22 16:39:35 2023: /gpfs/fs1/home/ac.xylar/chrysal...
    parent_id:      lsd2k42w1r\na4x6sqhkwb
    mesh_spec:      0.0
    file_id:        kufh9o2jwx
ds_120
<xarray.Dataset>
Dimensions:                   (nEdges: 87980, maxEdges2: 12, TWO: 2,
                               nVertices: 59329, vertexDegree: 3,
                               nCells: 28571, nVertLevels: 100, maxEdges: 6,
                               Time: 1)
Dimensions without coordinates: nEdges, maxEdges2, TWO, nVertices,
                                vertexDegree, nCells, nVertLevels, maxEdges,
                                Time
Data variables: (12/49)
    edgesOnEdge               (nEdges, maxEdges2) int32 ...
    weightsOnEdge             (nEdges, maxEdges2) float64 ...
    cellsOnEdge               (nEdges, TWO) int32 ...
    verticesOnEdge            (nEdges, TWO) int32 ...
    angleEdge                 (nEdges) float64 ...
    dcEdge                    (nEdges) float64 ...
    ...                        ...
    refTopDepth               (nVertLevels) float64 ...
    refZMid                   (nVertLevels) float64 ...
    refLayerThickness         (nVertLevels) float64 ...
    layerThickness            (Time, nCells, nVertLevels) float64 ...
    ssh                       (Time, nCells) float64 ...
    zMid                      (Time, nCells, nVertLevels) float64 ...
Attributes: (12/15)
    model_name:     mpas
    core_name:      ocean
    source:         MPAS
    Conventions:    MPAS
    git_version:    v4.0-973-g678b0d3
    on_a_sphere:    YES
    ...             ...
    y_period:       0.0
    history:        Mon Apr 24 15:11:05 2023: /gpfs/fs1/home/ac.xylar/chrysal...
    parent_id:      a3ix7sajjh\nfo1xwy6fbp\ne513bmrqm3\n
    mesh_spec:      0.0
    file_id:        f5z41zseqm
    NCO:            4.0.5

Working with Unstructured Grids using UXarray

Grid Representation

uxds_480 = ux.open_dataset(ds_file_480, ds_file_480)
uxds_480.uxgrid
<uxarray.Grid>
Original Grid Type: mpas
Grid Dimensions:
  * nMesh2_node: 3947
  * nMesh2_face: 1791
  * nMaxMesh2_face_nodes: 6
  * nMesh2_edge: 5754
Grid Coordinate Variables:
  * Mesh2_node_x: (3947,)
  * Mesh2_node_y: (3947,)
  * Mesh2_face_x: (1791,)
  * Mesh2_face_y: (1791,)
Grid Connectivity Variables:
  * Mesh2_face_nodes: (1791, 6)
  * Mesh2_edge_nodes: (5754, 2)
  * nNodes_per_face: (1791,)
uxds_120 = ux.open_dataset(ds_file_120, ds_file_120)
uxds_120.uxgrid
<uxarray.Grid>
Original Grid Type: mpas
Grid Dimensions:
  * nMesh2_node: 59329
  * nMesh2_face: 28571
  * nMaxMesh2_face_nodes: 6
  * nMesh2_edge: 87980
Grid Coordinate Variables:
  * Mesh2_node_x: (59329,)
  * Mesh2_node_y: (59329,)
  * Mesh2_face_x: (28571,)
  * Mesh2_face_y: (28571,)
Grid Connectivity Variables:
  * Mesh2_face_nodes: (28571, 6)
  * Mesh2_edge_nodes: (87980, 2)
  * nNodes_per_face: (28571,)

Geometries

Plotting with HoloViz

Conversion to GeoDataFrame

gdf_480_grid = uxds_480.uxgrid.to_geodataframe()
gdf_120_grid = uxds_120.uxgrid.to_geodataframe()

Nodes

hv.extension("matplotlib")

plot_kwargs = {"size": 5.0, "xlabel":"Longitude", "ylabel": "Latitude", "xlim": (-110, -50), "ylim": (0, 40),
               "coastline": True, "width": 800}
 hv.Layout(gdf_480_grid.hvplot.points(**plot_kwargs) + gdf_120_grid.hvplot.points(**plot_kwargs)).opts(fig_size=150)
/usr/share/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
hv.extension("bokeh")

plot_kwargs = {"s": 1.0, "xlabel":"Longitude", "ylabel": "Latitude", "xlim": (-110, -50), "ylim": (0, 40),
               "coastline": True}
hv.Layout(gdf_480_grid.hvplot.points(**plot_kwargs) + gdf_120_grid.hvplot.points(**plot_kwargs))

Edges

hv.extension("matplotlib")

plot_kwargs = {"linewidth": 0.5, "xlabel":"Longitude", "ylabel": "Latitude", "xlim": (-110, -50), "ylim": (0, 40),
               "coastline": True, "width": 1600}
hv.Layout(gdf_480_grid.hvplot.paths(**plot_kwargs) + gdf_120_grid.hvplot.paths(**plot_kwargs)).opts(fig_size=150)
hv.extension("bokeh")

plot_kwargs = {"line_width": 0.5, "xlabel":"Longitude", "ylabel": "Latitude", "xlim": (-110, -50), "ylim": (0, 40),
               "coastline": True}
hv.Layout(gdf_480_grid.hvplot.paths(**plot_kwargs) + gdf_120_grid.hvplot.paths(**plot_kwargs))

Polygons

hv.extension("matplotlib")

plot_kwargs = {} #TODO 
# TODO: vector
# TODO: raster
hv.extension("bokeh")

plot_kwargs = {} #TODO 
# TODO: vector
# TODO: raster

Summary

Add one final --- marking the end of your body of content, and then conclude with a brief single paragraph summarizing at a high level the key pieces that were learned and how they tied to your objectives. Look to reiterate what the most important takeaways were.

What’s next?

Let Jupyter book tie this to the next (sequential) piece of content that people could move on to down below and in the sidebar. However, if this page uniquely enables your reader to tackle other nonsequential concepts throughout this book, or even external content, link to it here!

Resources and references

Finally, be rigorous in your citations and references as necessary. Give credit where credit is due. Also, feel free to link to relevant external material, further reading, documentation, etc. Then you’re done! Give yourself a quick review, a high five, and send us a pull request. A few final notes:

  • Kernel > Restart Kernel and Run All Cells... to confirm that your notebook will cleanly run from start to finish

  • Kernel > Restart Kernel and Clear All Outputs... before committing your notebook, our machines will do the heavy lifting

  • Take credit! Provide author contact information if you’d like; if so, consider adding information here at the bottom of your notebook

  • Give credit! Attribute appropriate authorship for referenced code, information, images, etc.

  • Only include what you’re legally allowed: no copyright infringement or plagiarism

Thank you for your contribution!